
/**
 *	\file
 *	Defines the sun::system_config singleton.
 *	\author Sean Tromans
 */

#ifndef	SUN_INTERNAL_SYSTEM_HPP
#define	SUN_INTERNAL_SYSTEM_HPP

#include <sun/exception/exception.hpp>
#include <needs_more_ninja/template/singleton/singleton.hpp>
#include <needs_more_ninja/template/hashed_string.hpp>
#include <boost/unordered_map.hpp>
#include <boost/any.hpp>
#include <exception>

namespace sun
{

	/**
	 *	Exception to throw when a config is already assigned within the system.
	 *	\author Sean Tromans
	 */
	class duplicate_config : public exception
    {
    public:

		duplicate_config( nmn::hashed_string const & c )
			:	exception( nmn::create_string( "sun::duplicate_config: attempted to assign to a system config more than once: \n%1%", c.str( ) ) )
		{ }
    };

	/**
	 *	Exception to throw when a config is not found within the system.
	 *	\author Sean Tromans
	 */
	class config_not_found : public exception
    {
    public:

		config_not_found( nmn::hashed_string const & c )
			:	exception( nmn::create_string( "sun::config_not_found: could not find the config specified: \n%1%", c.str( ) ) )
		{ }
    };

	/**
	 *	Singelton class object which keeps a reference to various globally required system configuration values.
	 *	\author Sean Tromans
	 */
	class system_config	: public nmn::singleton<system_config>
	{
		//
		//	Public Member Types
		//
		public:

			/**	Container mapping configuration parameter name to the object. */
			typedef	boost::unordered_map< nmn::hashed_string, boost::any >	config_param_map;

		//
		//	Public Member Functions
		//
		public:

			/**
			 *	Add a configuration parameter.
			 *	@param name The unique name of the configuration parameter.
			 *	@param value The value to assign this parameter.
			 *	\throws sun::duplicate_config if the config already existed.
			 *	\author Sean Tromans
			 */
			template < typename TType >
			void	add_param( nmn::hashed_string const & name, TType const & value );

			/**
			 *	Retreive the configuration parameter with the given name.
			 *	@param name The unique name of the configuration parameter to find.
			 *	\throws sun::config_not_found if the config does not currently exist within the system.
			 *	\throws boost::bad_any_cast if the parameter was not of type TType.
			 *	\author Sean Tromans
			 */
			template < typename TType >
			TType const & get_param( nmn::hashed_string const & name );

		//
		//	Private Member Types
		//
		private:

		//
		//	Private Member Functions
		//
		private:

		//
		//	Private Member Variables
		//
		private:

			config_param_map	m_params;
	};
}

#include <sun/internal/system.inl>

#endif	//SUN_INTERNAL_SYSTEM_HPP
